#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_system.h"
#include "tm1638_enevt.h"
#include "TM1638.h"
#include <stdio.h>
#include "driver/gpio.h"
#include "rom/ets_sys.h"


static const char* TAG = "tm1638_event_loops";
static const char* err =NULL;
static esp_event_loop_args_t  event_loop_args={
        .queue_size = 5,            //队列长度
        .task_name = "loop_tm1638", // 将创建任务的名称，用于用户时间循环
        .task_priority = 5,   //任务优先级，默认当前任务优先级
        .task_stack_size = 3000,                    //任务堆栈大小
        .task_core_id = tskNO_AFFINITY,              //指定core_id处理0或1
    };

void run_tm1638_event_handler(void* handler_arg, esp_event_base_t base, int32_t id, void* event_data)
{
    // 事件处理程序逻辑
    switch(id){
        case    TM1638_ERR_EVENT:       //错误
            ESP_LOGI(TAG, "TM1638_ERR_EVENT %s\n",(char*)event_data);
            //printf("%s\n",(char*)event_data);
            break;
        case    TM1638_INIT_EVENT:       //初始化
            ESP_LOGI(TAG, "TM1638_INIT_EVENT %s\n",(char*)event_data);
            //printf("%s\n",(char*)event_data);
            break;
        case    TM1638_LED_UP_EVENT:	//开灯
            ESP_LOGI(TAG, "TM1638_LED_UP_EVENT %d\n",*(uint8_t*)event_data);
            //printf("%d\n",*(uint8_t*)event_data);
        case    TM1638_LED_OFF_EVENT:  //关灯
            ESP_LOGI(TAG, "TM1638_LED_OFF_EVENT %d\n",*(uint8_t*)event_data);
            //printf("%d\n",*(uint8_t*)event_data);
            break;
        case    TM1638_KEY_DOWN_EVENT:   //按键弹起
            ESP_LOGI(TAG, "TM1638_KEY_DOWN_EVENT %d\n",*(uint8_t*)event_data);

        case    TM1638_KEY_UP_EVENT:   //按键弹起
            ESP_LOGI(TAG, "TM1638_KEY_UP_EVENT %d\n",*(uint8_t*)event_data);
            break;
        case    TM1638_NIXIE_TUBE_INPUT: //数码管输入
            ESP_LOGI(TAG, "TM1638_NIXIE_TUBE_INPUT %d\n",*(uint8_t*)event_data);
            //printf("%s\n",(char*)event_data);
            break;
        case    TM1638_DEL_EVENT:        //销毁
            ESP_LOGI(TAG, "TM1638_DEL_EVENT %s\n",(char*)event_data);
            printf("%s\n",(char*)event_data);
            break;
    }
}

//事件库定义
ESP_EVENT_DEFINE_BASE(TM1638_EVENTS);		//TM1638事件库定义

tm1638_drive * tm1638_drive_malloc(esp_event_handler_t handler){
    tm1638_drive * drive =malloc(sizeof(tm1638_drive));
    if(drive != NULL){
        memset(drive, 0, sizeof(*drive));
        ESP_LOGI(TAG, "malloc tm1638_drive %p", drive);
    }else{
        ESP_LOGI(TAG, "malloc tm1638_drive 失败");
    }
    //return drive;
    drive->init=0;
    if(drive->init==0){
        esp_event_loop_create(&event_loop_args, &(drive->tm1638_event_loop_handle));

        if(handler ==NULL)esp_event_handler_register_with(drive->tm1638_event_loop_handle,TM1638_EVENTS, ESP_EVENT_ANY_ID, run_tm1638_event_handler,NULL);
        else esp_event_handler_register_with(drive->tm1638_event_loop_handle,TM1638_EVENTS, ESP_EVENT_ANY_ID,handler,drive);

        drive->led=0;
        drive->key=8;
        strcpy(drive->num,"\x40\x40\x40\x40\x40\x40\x40\x40");

        init_gpio();
        init_TM1638();
        	for(uint8_t i=0;i<8;i++){
                Write_DATA(i<<1,drive->num[i]);
            }
        err="初始化成功";
        esp_event_post_to(drive->tm1638_event_loop_handle, TM1638_EVENTS,TM1638_INIT_EVENT,err,strlen(err),20);
        drive->init=1;
    }else{
        //ESP_LOGI(TAG, " tm1638_drive 初始化失败！");
        err="tm1638_drive 初始化失败！";
        esp_event_post_to(drive->tm1638_event_loop_handle, TM1638_EVENTS,TM1638_ERR_EVENT,err,strlen(err),20);
    }
    return drive;
}


//drive，输出,用于保存tm1638_drive结构体
/* esp_err_t tm1638_drive_create(tm1638_drive * drive,esp_event_handler_t handler){
    drive=(tm1638_drive *)malloc(sizeof(tm1638_drive));
    if(drive == NULL){
            printf("tm1638_drive malloc err!\n");
            return -1;
        }
    drive->led=0;
    drive->key=0;

    esp_event_loop_args_t  event_loop_args={
        .queue_size = 5,            //队列长度
        .task_name = "loop_tm1638", // 将创建任务的名称，用于用户时间循环
        .task_priority = uxTaskPriorityGet(NULL),   //任务优先级，默认当前任务优先级
        .task_stack_size = 3000,                    //任务堆栈大小
        .task_core_id = tskNO_AFFINITY,              //指定core_id处理0或1
    };
    
    
    esp_event_loop_create(&event_loop_args, &(drive->tm1638_event_loop_handle));

    if(handler ==NULL)esp_event_handler_register_with(drive->tm1638_event_loop_handle,TM1638_EVENTS, ESP_EVENT_ANY_ID, run_tm1638_event_handler,NULL);
    else esp_event_handler_register_with(drive->tm1638_event_loop_handle,TM1638_EVENTS, ESP_EVENT_ANY_ID,handler,drive);
    init_gpio();
    init_TM1638();
    err="初始化成功";
    esp_event_post_to(drive->tm1638_event_loop_handle, TM1638_EVENTS,TM1638_INIT_EVENT,err,strlen(err),10);
    return ESP_OK;
} */

//查询指定编号led状态，0关，1亮，no==8时，返回drive->led,大于8返回错误码！
uint8_t tm1638_drive_led_get(tm1638_drive * drive,uint8_t no){
    if(drive==NULL) return -1;
    uint8_t n=0;
    if(no>8)return drive->led & (1<<no)?1:0;
    if(no==8)return drive->led;
    err="获取led参数错误！";
    esp_event_post_to(drive->tm1638_event_loop_handle, TM1638_EVENTS,TM1638_ERR_EVENT,err,strlen(err),20);
    return -1;

}

uint8_t tm1638_drive_led_up(tm1638_drive * drive,uint8_t no){
    if(drive==NULL) return -1;
    if(drive->led & (1<<no)){
        err="指定led已经是打开的了！";
        esp_event_post_to(drive->tm1638_event_loop_handle, TM1638_EVENTS,TM1638_ERR_EVENT,err,strlen(err),20);
        return -1;
        }
    else{
        drive->led |=(1<<no);
        //printf("开灯%d",no);
        Write_allLED(drive->led);
        esp_event_post_to(drive->tm1638_event_loop_handle, TM1638_EVENTS,TM1638_LED_UP_EVENT,&no,sizeof(no),20);
        return 0;
    }

}

uint8_t tm1638_drive_led_off(tm1638_drive * drive,uint8_t no){
    if(drive==NULL) return -1;
    if(drive->led & (1<<no)){
        drive->led &= ~(1<<no);
        Write_allLED(drive->led);
        esp_event_post_to(drive->tm1638_event_loop_handle, TM1638_EVENTS,TM1638_LED_OFF_EVENT,&no,sizeof(no),20);
        return 0;
        }
    else{
        err="指定led已经是关闭的了！";
        esp_event_post_to(drive->tm1638_event_loop_handle, TM1638_EVENTS,TM1638_ERR_EVENT,err,strlen(err),20);
        return -1;
    }
}
//获取按键，并发出按键事件
uint8_t tm1638_drive_key_get(tm1638_drive * drive){
    if(drive==NULL) return -1;
    drive->key=Read_key();
    vTaskDelay(20 / portTICK_PERIOD_MS);
    /* if(drive->key == 8){
        drive->key=Read_key();
        vTaskDelay(10 / portTICK_PERIOD_MS);
        //ets_delay_us(15000);
    } */
    
    if(drive->key < 8 && drive->key == Read_key()){
        esp_event_post_to(drive->tm1638_event_loop_handle, TM1638_EVENTS,TM1638_KEY_DOWN_EVENT,&(drive->key),sizeof(drive->key),10);
        while(Read_key() == drive->key)ets_delay_us(15000); 
        if(Read_key() == 8){
            esp_event_post_to(drive->tm1638_event_loop_handle, TM1638_EVENTS,TM1638_KEY_UP_EVENT,&(drive->key),sizeof(drive->key),10);
        }    
    }
    return drive->key;
}

uint8_t tm1638_drive_num_input(tm1638_drive * drive,uint8_t add,u_char data){
    if(drive==NULL) return -1;
    if(data==NULL) {
        err="字符不合法！";
        esp_event_post_to(drive->tm1638_event_loop_handle, TM1638_EVENTS,TM1638_ERR_EVENT,err,strlen(err),10);
        return -2;
    }
    drive->num[add]=data;
    esp_event_post_to(drive->tm1638_event_loop_handle, TM1638_EVENTS,TM1638_NIXIE_TUBE_INPUT,&add,sizeof(add),10);
    for(uint8_t i=0;i<8;i++){
        Write_DATA(i<<1,drive->num[i]);
    }
    return 0;
}


esp_err_t tm1638_drive_del(tm1638_drive ** drive){
    if(drive!=NULL && (*drive!=NULL)){
        ESP_LOGI(TAG, " %p TM1638设备注销!",*drive);
        err="TM1638设备注销！";
        esp_event_post_to((*drive)->tm1638_event_loop_handle, TM1638_EVENTS,TM1638_DEL_EVENT,err,strlen(err),10);
        free(*drive);
    }else{
        err="TM1638设备注销失败！";
        esp_event_post_to((*drive)->tm1638_event_loop_handle, TM1638_EVENTS,TM1638_ERR_EVENT,err,strlen(err),10);
    }
    return ESP_OK;

}